-- Tree Traversal --

Traverse.Declarations .env (.decls, .remains) :-
	Traverse.Declaration .env .decls,
	Traverse.Declarations .env .remains #
Traverse.Declarations . $ #

Traverse.Declaration .env (TYPEDEF .type .name) :-
	Traverse.Type .env .type #
Traverse.Declaration .env (VARDEF .type .name) :-
	Traverse.Type .env .type #
Traverse.Declaration .env (VARDEFVALUE .type .name .value) :-
	Traverse.Type .env .type,
	Traverse.Expression .env .type #

Traverse.Type . VOID #
Traverse.Type . (INTTYPE .i) #
Traverse.Type .env (PTR .i) :- Traverse.Type .env .i #
Traverse.Type .env (ARRAY .size .i) :- Traverse.Type .env .i #
Traverse.Type .env (CLASS .decls) :-
	Traverse.Declarations (.decls, .env) .decls #
Traverse.Type .env (FUNC .s .return .block) :-
	Traverse.Declarations .env .parms,
	Traverse.Type .env .return,
	Traverse.Statements .env .block #
Traverse.Type .env (TYPENAME .name) #

Traverse.Statements .env (.stmt, .remains) :-
	Traverse.Statement .env .stmt,
	Traverse.Statements .env .remains #
Traverse.Statements . $ #

Traverse.Statement .env (BLOCK .stmts) :- Traverse.Statements .env .stmts #
Traverse.Statement .env (TYPEDEF .type .name) :- Traverse.Type .env .type #
Traverse.Statement .env (VARDEF .type .name) :- Traverse.Type .env .type #
Traverse.Statement .env (VARDEFVALUE .type .name .value) :-
	Traverse.Type .env .type,
	Traverse.Expression .env .value #
Traverse.Statement .env (IF .cond .then) :-
	Traverse.Expression .env .cond,
	Traverse.Statement .env .then #
Traverse.Statement .env (IFELSE .cond .then .else) :-
	Traverse.Expression .env .cond,
	Traverse.Statement .env .then,
	Traverse.Statement .env .else #
Traverse.Statement .env (WHILE .cond .do) :-
	Traverse.Expression .env .cond,
	Traverse.Statement .env .do #
Traverse.Statement .env (EXPR .expr) :-
	Traverse.Expression .env .expr #

Traverse.Expression .env (ASGop .l .r) :-
	Traverse.Expression .env .l,
	Traverse.Expression .env .r #
Traverse.Expression .env (ADDop .l .r) :-
	Traverse.Expression .env .l,
	Traverse.Expression .env .r #
Traverse.Expression .env (SUBop .l .r) :-
	Traverse.Expression .env .l,
	Traverse.Expression .env .r #
Traverse.Expression .env (MULop .l .r) :-
	Traverse.Expression .env .l,
	Traverse.Expression .env .r #
Traverse.Expression .env (DIVop .l .r) :-
	Traverse.Expression .env .l,
	Traverse.Expression .env .r #

Traverse.Expression .env (CALL .func .parms) :-
	Traverse.Expression .env .func,
	Traverse.Parameters .env .parms #

Traverse.Parameters .env $ #
Traverse.Parameters .env (.var, .remains) :-
	Traverse.Expression .env .var,
	Traverse.Parameters .env .remains #

Traverse.Expression .env (MEMBER .v .field) :- Traverse.Expression .env .v #

Traverse.Expression .env (NUM .n) #
Traverse.Expression .env (STR .s) #
Traverse.Expression .env (VAR .v) #
Traverse.Declarations .env (.decls, .remains) :-
	Traverse.Declaration .env .decls,
	Traverse.Declarations .env .remains #


-- Tree Transformation --

Process.Declarations .env
	(.decls, .remains => .decls1, .remains1) :-
	Process.Declaration .env (.decls => .decls1),
	Process.Declarations .env (.remains => .remains1) #
Process.Declarations . ($ => $) #

Process.Declaration .env (TYPEDEF .type .name => TYPEDEF .type1 .name) :-
	Process.Type .env (.type => .type1) #
Process.Declaration .env (VARDEF .type .name => VARDEF .type1 .name) :-
	Process.Type .env (.type => .type1) #
Process.Declaration .env (VARDEFVALUE .type .name .value =>
	VARDEFVALUE .type1 .name .value1) :-
	Process.Type .env (.type => .type1),
	Process.Expression .env (.value => .value1) #

Process.Type . (VOID => VOID) #
Process.Type . (INTTYPE .i => INTTYPE .i) #
Process.Type .env (PTR .i => PTR .i1) :-
	Process.Type .env (.i => .i1) #
Process.Type .env (ARRAY .size .i => ARRAY .size .i1) :-
	Process.Type .env (.i => .i1) #
Process.Type .env (CLASS .decls => CLASS .decls1) :-
	Process.Declarations (.decls, .env) (.decls => .decls1) #
Process.Type .env
	(FUNC .parms .return .block => FUNC .parms1 .return1 .block1) :-
	Process.Declarations .env (.parms => .parms1),
	Process.Type .env (.return => .return1),
	Process.Statements .env (.block => .block1) #
Process.Type .env (TYPENAME .name => TYPENAME .name) #

Process.Statements .env (.stmt, .remains => .stmt1, .remains1) :-
	Process.Statement .env (.stmt => .stmt1),
	Process.Statements .env (.remains => .remains1) #
Process.Statements . ($ => $) #

Process.Statement .env (BLOCK .stmts => BLOCK .stmts1) :-
	Process.Statements .env (.stmts => .stmts1) #
Process.Statement .env (TYPEDEF .type .name => TYPEDEF .type1 .name) :-
	Process.Type .env (.type => .type1) #
Process.Statement .env (VARDEF .type .name => VARDEF .type1 .name) :-
	Process.Type .env (.type => .type1) #
Process.Statement .env (VARDEFVALUE .type .name .value =>
	VARDEF .type1 .name .value1) :-
	Process.Type .env (.type => .type1),
	Process.Expression .env (.value => .value1) #
Process.Statement .env (IF .cond .then => IF .cond1 .then1) :-
	Process.Expression .env (.cond => .cond1),
	Process.Statement .env (.then => .then1) #
Process.Statement .env
	(IFELSE .cond .then .else => IFELSE .cond1 .then1 .else1) :-
	Process.Expression .env (.cond => .cond1),
	Process.Statement .env (.then => .then1),
	Process.Statement .env (.else => .else1) #
Process.Statement .env (WHILE .cond .do => WHILE .cond1 .do1) :-
	Process.Expression .env (.cond => .cond1),
	Process.Statement .env (.do => .do1) #
Process.Statement .env (EXPR .expr => EXPR .expr1) :-
	Process.Expression .env (.expr => .expr1) #

Process.Expression .env (ASGop .l .r => ASGop .l1 .r1) :-
	Process.Expression .env (.l => .l1),
	Process.Expression .env (.r => .r1) #
Process.Expression .env (ADDop .l .r => ADDop .l1 .r1) :-
	Process.Expression .env (.l => .l1),
	Process.Expression .env (.r => .r1) #
Process.Expression .env (SUBop .l .r => SUBop .l1 .r1) :-
	Process.Expression .env (.l => .l1),
	Process.Expression .env (.r => .r1) #
Process.Expression .env (MULop .l .r => MULop .l1 .r1) :-
	Process.Expression .env (.l => .l1),
	Process.Expression .env (.r => .r1) #
Process.Expression .env (DIVop .l .r => DIVop .l1 .r1) :-
	Process.Expression .env (.l => .l1),
	Process.Expression .env (.r => .r1) #

Process.Expression .env (CALL .func .parms => CALL .func1 .parms1) :-
	Process.Expression .env (.func => .func1),
	Process.Parameters .env (.parms => .parms1) #

Process.Parameters . ($ => $) #
Process.Parameters .env (.var, .remains => .var1, .remains1) :-
	Process.Expression .env (.var => .var1),
	Process.Parameters .env (.remains => .remains1) #

Process.Expression .env (MEMBER .v .field => MEMBER .v1 .field) :-
	Process.Expression .env (.v => .v1) #

Process.Expression .env (NUM .n => NUM .n) #
Process.Expression .env (STR .s => STR .s) #
Process.Expression .env (VAR .v => VAR .v) #
